/*FreeMind - A Program for creating and viewing Mindmaps
 *Copyright (C) 2000-2006  Joerg Mueller, Daniel Polansky, Christian Foltin and others.
 *
 *See COPYING for Details
 *
 *This program is free software; you can redistribute it and/or
 *modify it under the terms of the GNU General Public License
 *as published by the Free Software Foundation; either version 2
 *of the License, or (at your option) any later version.
 *
 *This program is distributed in the hope that it will be useful,
 *but WITHOUT ANY WARRANTY; without even the implied warranty of
 *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *GNU General Public License for more details.
 *
 *You should have received a copy of the GNU General Public License
 *along with this program; if not, write to the Free Software
 *Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * Created on 10.01.2006
 */
/*$Id: FreeMindCommon.java,v 1.1.2.2.2.36 2008/05/04 16:22:57 christianfoltin Exp $*/
package freemind.main;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLDecoder;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Locale;
import java.util.Properties;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.Vector;
import java.util.logging.Logger;


/**
 * @author foltin
 * 
 */
public class FreeMindCommon {

	public static final String FREEMIND_FILE_EXTENSION_WITHOUT_DOT = "mm";

	public static final String FREEMIND_FILE_EXTENSION = "."+FREEMIND_FILE_EXTENSION_WITHOUT_DOT;

	public static final String POSTFIX_TRANSLATE_ME = "[translate me]";

    private class FreemindResourceBundle extends ResourceBundle{
        private PropertyResourceBundle languageResources;
        private PropertyResourceBundle defaultResources;
        FreemindResourceBundle(){
            try {
                String lang = getProperty(RESOURCE_LANGUAGE);
                if (lang == null || lang.equals("automatic")) {
                    lang = Locale.getDefault().getLanguage() + "_"
                            + Locale.getDefault().getCountry();
                    if (getLanguageResources(lang) == null) {
                        lang = Locale.getDefault().getLanguage();
                        if (getLanguageResources(lang) == null) {
                            // default is english.
                            lang = DEFAULT_LANGUAGE;
                        }
                    }
                }
                if("no".equals(lang)){
                	//Bugs item #1935818
                	lang="nb";
                }
                languageResources = getLanguageResources(lang);
                /* fc, 26.4.2008. the following line is a bug, as the defaultResources are used,
                 * even, when a single string is missing inside a bundle and not only, 
                 * when the complete bundle is missing.
                 */ 
//                if(languageResources == null)
                defaultResources = getLanguageResources(DEFAULT_LANGUAGE);
            } catch (Exception ex) {
                freemind.main.Resources.getInstance().logException(             ex);
                logger.severe("Error loading Resources");
            }
//            printResourceTable();
        }

//        /** This is useful, if you want to see all resource strings in a HTML table.
//         * Just rename the log file to log.0.html, open in a browser and set the 
//         * coding to UTF-8 */
//		private void printResourceTable() {
//			StringBuffer b = new StringBuffer("<html><body><table>");
//            Set keySet = languageResources.keySet();
//            Vector keys = new Vector(keySet);
//            Collections.sort(keys);
//			for (Iterator iterator = keys.iterator(); iterator.hasNext();) {
//				String key = (String) iterator.next();
//				b.append("<tr><td>" + key + "</td><td>" + languageResources.getString(key)+"</td></tr>\n");
//			}
//            b.append("</table></body></html>");
//            logger.info(b.toString());
//		}

        /**
         * @throws IOException
         */
        private PropertyResourceBundle getLanguageResources(String lang)
                throws IOException {
            URL systemResource = mFreeMindMain.getResource("Resources_" + lang
                    + ".properties");
            if (systemResource == null) {
                return null;
            }
            InputStream in = systemResource.openStream();
            if (in == null) {
                return null;
            }
            PropertyResourceBundle bundle = new PropertyResourceBundle(in);
            in.close();
            return bundle;
        }

        protected Object handleGetObject(String key) {
            try {
                return languageResources.getString(key);
            } catch (Exception ex) {
                logger.severe("Warning - resource string not found:" + key);
                return defaultResources.getString(key) + POSTFIX_TRANSLATE_ME;
            }
        }

        public Enumeration getKeys() {
            return defaultResources.getKeys();
        }
        
        String getResourceString(String key) {
            try {
                return getString(key);
            } catch (Exception ex) {
                return key;
            }
        }

        String getResourceString(String key, String resource) {
        	try {
        		try {
        			return languageResources.getString(key);
        		} catch (Exception ex) {
        			return defaultResources.getString(key) + POSTFIX_TRANSLATE_ME;
        		}
        	} catch (Exception e) {
        		return resource;
        	}
        }
    }

	public static final String RESOURCE_LANGUAGE = "language";

    public static final String RESOURCE_ANTIALIAS = "antialias";

    public static final String DEFAULT_LANGUAGE = "en";

    public static final String LOCAL_PROPERTIES = "LocalProperties.";

	private final FreeMindMain mFreeMindMain;

    private String baseDir;

    private FreemindResourceBundle resources;

    /**
     * Holds the last opened map.
     */
    public static final String ON_START_IF_NOT_SPECIFIED = "onStartIfNotSpecified";
    public static final String LOAD_LAST_MAP = "loadLastMap";
    public static final String SAVE_ONLY_INTRISICALLY_NEEDED_IDS = "save_only_intrisically_needed_ids";

	private static Logger logger = null;

	/**
	 * 
	 */
	public FreeMindCommon(FreeMindMain main) {
		super();
		// TODO Auto-generated constructor stub
		this.mFreeMindMain = main;
		if (logger == null)
			logger = main.getLogger(this.getClass().getName());
	}

	public String getProperty(String key) {
		return mFreeMindMain.getProperty(key);
	}
    
    private void setDefaultProperty(String key, String value){
        mFreeMindMain.setDefaultProperty(key, value);
    }

	/** Returns the ResourceBundle with the current language */
    public ResourceBundle getResources() {
		if (resources == null) {
            resources = new FreemindResourceBundle();
		}
		return resources;
	}

    public String getResourceString(String key) {
        return ((FreemindResourceBundle)getResources()).getResourceString(key);
    }

    public String getResourceString(String key, String resource) {
        return ((FreemindResourceBundle)getResources()).getResourceString(key, resource);
    }

    public void clearLanguageResources() {
		resources = null;
	}
    
	public ClassLoader getFreeMindClassLoader() {
		ClassLoader classLoader = this.getClass().getClassLoader();
		try {
			return new URLClassLoader(new URL[] { new File(getFreemindBaseDir()).toURI().toURL() }, classLoader);
		} catch (MalformedURLException e) {
			freemind.main.Resources.getInstance().logException(e);
			return classLoader;
		}
	}

	/**
     * Old version using String manipulation out of the classpath to find the base dir.
	 */
	public String getFreemindBaseDirOld() {
        if(baseDir == null){
            final String classPath = System.getProperty("java.class.path");
            final String mainJarFile = "freemind.jar";
            int lastpos = classPath.indexOf(mainJarFile);
            int firstpos = 0;
            // if freemind.jar is not found in the class path use user.dir as Basedir
            if(lastpos == -1){
                baseDir = System.getProperty("user.dir");
                logger.info("Basedir is user.dir: "+baseDir);
                return baseDir;
            }
            /* fc: Now, if freemind.jar is the first, firstpos == -1. 
             * This results in bad results in the substring method, or not??*/
            firstpos = classPath.lastIndexOf(File.pathSeparator, lastpos) + 1;
            lastpos -= 1;
            if (lastpos > firstpos) {
            	logger.info("First " + firstpos +  " and last " + lastpos + " and string " + classPath);
                baseDir = classPath.substring(firstpos, lastpos);
            }
            else 
                baseDir = "";
            final File basePath = new File(baseDir);
            baseDir = basePath.getAbsolutePath();
            logger.info("First basedir is: "+baseDir);
            /* I suppose, that here, the freemind.jar is removed together with the last path. 
             * Example: /home/foltin/freemindapp/lib/freemind.jar gives 
             * /home/foltin/freemindapp */
            lastpos = baseDir.lastIndexOf(File.separator);
            if (lastpos > -1) 
                baseDir = baseDir.substring(0, lastpos);
            logger.info("Basedir is: "+baseDir);
        }
        return baseDir;
	}
    /* We define the base dir of FreeMind as the directory where accessories,
     * plugins and other things are to be found.
     * We expect it to be either the directory where the
     * main jar file is (freemind.jar), or the root of the class hierarchy
     * (if no jar file is used), after any 'lib' directory is removed.
     * One can overwrite this definition by setting the freemind.base.dir
     * property.
     */
    public String getFreemindBaseDir() {
        if (baseDir == null) {
            try {
                File file;
                String dir = System.getProperty("freemind.base.dir");
                if (dir == null) {
                    // Property isn't set, we try to find the
                    // base directory ourselves.
                    // System.err.println("property not set");
                    // We locate first the current class.
                    String classname = this.getClass().getName();
                    URL url = this.getClass().getResource(
                            classname.replaceFirst("^"
                                    + this.getClass().getPackage().getName()
                                    + ".", "")
                                    + ".class");
                    // then we create a file out of it, after
                    // removing file: and jar:, removing everything
                    // after !, as well as the class name part.
                    // Finally we decode everything (e.g. %20)
                    // TODO: is UTF-8 always the right value?
                    file = new File(URLDecoder.decode(
                            url.getPath().replaceFirst("^(file:|jar:)+", "")
                                    .replaceFirst("!.*$", "").replaceFirst(
                                            classname.replace('.', '/')
                                                    + ".class$", ""), "UTF-8"));
                    // if it's a file, we take its parent, a dir
                    if (file.isFile())
                        file = file.getParentFile();
                    /* Now, we remove the lib directory:
                     * Example: /home/foltin/freemindapp/lib/freemind.jar gives 
                     * /home/foltin/freemindapp */
                    if (file.getName().equals("lib"))
                        file = file.getParentFile();
                } else {
                    file = new File(dir);
                }
                // then we check if the directory exists and is really
                // a directory.
                if (!file.exists()) {
                    throw new IllegalArgumentException("FreeMind base dir '"
                            + file + "' does not exist.");
                }
                if (!file.isDirectory()) {
                    throw new IllegalArgumentException(
                            "FreeMind base dir (!) '" + file
                                    + "' is not a directory.");
                }
                // set the static variable
                baseDir = file.getCanonicalPath();
                logger.info("Basedir is: "+baseDir);
            } catch (Exception e) {
                Resources.getInstance().logException(e);
                throw new IllegalArgumentException(
                        "FreeMind base dir can't be determined.");
            }            
        }
        // return the value of the static variable
        return baseDir;
    }

    

    public String getAdjustableProperty(final String label) {
        String value = getProperty(label);
        if(value == null){
            return value;
        }
        if(value.startsWith("?") && ! value.equals("?")){
            // try to look in the language specific properties
        	String localValue = ((FreemindResourceBundle)getResources()).getResourceString(LOCAL_PROPERTIES + label, null);
        	value = localValue == null ? value.substring(1).trim() : localValue;
        	setDefaultProperty(label, value);
        }
        return value;
    }

	public void loadUIProperties(Properties props) {
//		props.put(FreeMind.RESOURCES_BACKGROUND_COLOR, Tools.colorToXml(UIManager.getColor("text")));
//		props.put(FreeMind.RESOURCES_NODE_TEXT_COLOR, Tools.colorToXml(UIManager.getColor("textText")));
//		props.put(FreeMind.RESOURCES_SELECTED_NODE_COLOR, Tools.colorToXml(UIManager.getColor("textHighlight")));
//		props.put(FreeMind.RESOURCES_SELECTED_NODE_TEXT_COLOR, Tools.colorToXml(UIManager.getColor("textHighlightText")));
	}


    
}
